﻿//----------------------------------------------------------------
// Desc: 关键帧动画处理器，中间线性插值
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2010-12-10
//
// Update Date : 
//
// Copyright (c) Fuel Game Engine (http://www.fge-engine.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


class FKeyAnimation : public IFMemObject
{
    FDECLARE_CLASS(FKeyAnimation)

protected:
    enum enumBitCombination
    {
        eBitLoop        = 1<<0,         // 循环
        eBitPingpong    = 1<<1,         // 对弹
        eBitStopAtEnd   = 1<<2,         // 停在尾部
    };

public:
    enum enumRunMode
    {
        eNormal_once    = 0,            // 单次
        eNormal_to_end  = eBitStopAtEnd,// 单次并停在尾部
        eNormal_loop    = eBitLoop,     // 循环
        ePingpong_once  = eBitPingpong, // 顺逆
        ePingpong_loop  = eBitPingpong|eBitStopAtEnd,// 顺逆循环
    };

    struct FPOINT
    {
        float X, Y, Z;
    };

    struct FKEY
    {
        float frame;    // 对帧ID支持
        FPOINT p;       // 对位置支持
        float scale;    // 对缩放支持
        float rot;      // 对旋转支持
        FKEY(){ set(0, 0, 0, 0, 0, 0); }
        FKEY(float f, float x, float y, float z, float s, float r){ set(f, x, y, z, s, r); }
        FINLINE void set(float f, float x, float y, float z, float s, float r);
    };

    typedef BYTE FKA_MODE;
    typedef_vector(FKEY, _fkey);

    FKeyAnimation();
    FKeyAnimation(float frame_count, float frame_interval, FKA_MODE mode);
    virtual~FKeyAnimation(){ vKeyList.clear(); }

    // 刷新关键帧动画处理器
    void Update();
    // 插入关键点
    void Insert(FKEY& key, bool ignore_same_key = false);
    // 获取指定帧数据
    void GetKey(float frames, FKEY* key);
    // 开始播放
    void Play();
    // 结速播放
    void Stop();
    // 设置当前帧
    void SetCurKey(float i){ nCurFrame = i; GetKey(nCurFrame, &nCurKey);}
    // 取得当前帧位置
    float GetCurFrame(){ return nCurFrame; }
    // 是否在播放中
    bool IsPlaying(){ return bIsPlaying; }
    // 是否已经到了两端，可循环判断处理
    bool IsDone(){ if (nDoneCount > 0){ nDoneCount--; return true; } return false; }
    // 取动关键点总数
    int GetKeyCount(){ return (int)vKeyList.size(); };
    // 取得指定关键点
    FKeyAnimation::FKEY* GetKey(int index){ return &vKeyList[index]; }
    // 取得首帧数据
    FKeyAnimation::FKEY* GetFirstKey(){ FASSERT(vKeyList.size() > 1, _T("没有初始化")); return &vKeyList[0]; }
    // 取当前帧数据
    FKeyAnimation::FKEY* GetCurKey()  { FASSERT(vKeyList.size() > 1, _T("没有初始化")); return &nCurKey; }
    // 取尾帧数据
    FKeyAnimation::FKEY* GetEndKey()  { FASSERT(vKeyList.size() > 1, _T("没有初始化")); return &vKeyList[vKeyList.size() - 1]; }
    // 取得帧总数
    float GetFrameCount(){ return nFrameCount; }

private:
    float nFrameCount;      // 总帧数
    float nFrameInterval;   // 每帧的时间间隔(毫秒)
    FKA_MODE nRunMode;      // 运行模式

    int nDoneCount;         // 到端点次数
    bool bIsPlaying;        // 开始状态
    float nCurFrame;        // 当前帧位置
    float nLstTime;         // 上次更新时间
    FKEY nCurKey;           // 当前关键点
    bool bInverting;        // 是否在翻转中
    fv_fkey vKeyList;       // 必须保证每个FKEY是连续的FKEY,通过FKEY.frame进行确认.
};


FINLINE void FKeyAnimation::FKEY::set(float f, float x, float y, float z, float s, float r)
{
    frame = f, p.X = x, p.Y = y, p.Z = z, scale = s, rot = r;
}